/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/////////////////////////////////////////////////////////////////////////

package sheep.view;

/////////////////////////////////////////////////////////////////////////

import sheep.model.graph.Graph;
import edu.uci.ics.jung.graph.Edge;
import edu.uci.ics.jung.graph.Vertex;
import edu.uci.ics.jung.graph.decorators.EdgeShape;
import edu.uci.ics.jung.visualization.AbstractLayout;
import edu.uci.ics.jung.visualization.DefaultSettableVertexLocationFunction;
import edu.uci.ics.jung.visualization.FRLayout;
import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
import edu.uci.ics.jung.visualization.ShapePickSupport;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;

import java.awt.Dimension;
import java.awt.GradientPaint;
import java.awt.Graphics;

import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.util.Calendar;
import java.util.Collections;
import java.util.LinkedList;
import java.util.LinkedList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import org.jdesktop.swingx.JXPanel;
import org.jdesktop.swingx.StackLayout;

import sheep.JUNG.utils.OurGrapheMouseListener;
import sheep.JUNG.utils.OurModalGraphMouse;
import sheep.JUNG.utils.OurPluggableRenderer;
import sheep.JUNG.utils.OurPopupGraphMousePlugin;
import sheep.JUNG.utils.OurVertexShape;
import sheep.controller.Workspace;
import sheep.model.Task;
import sheep.view.Component.SheepScrollbarUI;
import sheep.view.jung.utils.*;
/////////////////////////////////////////////////////////////////////////

/**
 *
 * @author geek
 */
public class GanttViewerExtend extends JXPanel{
  
  
  public void paintComponent(Graphics g){
    super.paintComponent(g);
  }
  
 
    
   private Workspace workSpace;
   
   private GANTTPanel ganttPanel;
   
   private GradientPaint gradient;
   
   static int dayMonthNumb[] = {31,28,31,30,31,30,31,31,30,31,30,31};  
   
   private GradientPaint   p1 = new GradientPaint(0, 0, new Color(0, 0, 0), 0, getHeight() - 1, new Color(100, 100, 100));
   int width, height;

   boolean fixedHeight = false;
   Color tabColor[]= {new Color(0,0, 255),new Color(40,40, 255),new Color(40,40, 255),
                      new Color(80,80, 255),new Color(120,120, 255),new Color(160,160, 255),
                      new Color(190,190, 255)};
   /////////////////////////////////////////////////////////////////////////
   
   public GanttViewerExtend(Workspace workSpace){
  
     this.workSpace = workSpace;

     //this.setOpaque(false);
     this.setBackground(Color.YELLOW); 
      

    
     ganttPanel = new GANTTPanel();
     width = ganttPanel.getPreferredSize().width;
     height = ganttPanel.getPreferredSize().height;
             
     ganttPanel.setPreferredSize(new Dimension ( width , height));
    
     this.setLayout(new StackLayout());
     JScrollPane graphZoomScrollPane = new JScrollPane(ganttPanel);
     graphZoomScrollPane.getVerticalScrollBar().setUI(new SheepScrollbarUI());
     graphZoomScrollPane.getHorizontalScrollBar().setUI(new SheepScrollbarUI());
     this.add(graphZoomScrollPane,BorderLayout.CENTER);

   }


///////////////////////////////////////////////////////////////////////// 
     class GANTTPanel extends JPanel{
       public GANTTPanel(){
         
       }

       int paintTasks (Task t, Graphics2D g2d, Calendar firstDate, Calendar lastDate, 
                          int days, int posY, int dec, int pos, Color c){
       int tot = 1;  
           if (paintTask(t,g2d,firstDate, lastDate, days, posY, dec, c)){
             Color c1 = tabColor[(dec+1) % tabColor.length];
              if (t.getTaskList(false,false).size() >0){
                LinkedList<Task> lst = t.getTaskList(false,false);
                Collections.sort(lst);
                for (Task t2 : lst){
                  if (t.getID() != t2.getID()){
                    dec++;
                    tot++;
                    tot+=paintTasks(t2,g2d,firstDate, lastDate, days, posY ,dec, pos, c1); 
                    dec+=t2.getTaskList(false,false).size()-1 ;
                     System.out.println("Gant extend : " + t2.getName());
                  }
                }
              }
              // Note suivante
             
            }
           return tot;
         
       }
       
       boolean paintTask (Task t, Graphics2D g2d, Calendar firstDate, Calendar lastDate, 
                          int days, int posY, int dec, Color c){
            // On ne dessine pas la tache en cours
            if (t.getID() != workSpace.getCurrentTask().getID()){
              
                // Taille d'une journee al 'ecran
                float stepx = days !=0?
                  (width -100) / days : 
                  (width-100) ;
                // num du mois de début
                int monthNum = firstDate.get(Calendar.MONTH);
                // decalage jusqu'au mois suivant
                int firstVert = dayMonthNumb[monthNum] - firstDate.get(Calendar.DAY_OF_MONTH);
                // Position de la premierer verticale
                int xPos = 50 + (int)(firstVert* stepx);


          
              g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f));
              
              Shape clip1 = g2d.getClip();
              int dayCount =0;
              
              // Calcul de la pos de debut
              Calendar diff1 = Calendar.getInstance();
              diff1.setTime(t.getEarliestBeginTime().getTime());
              
              if (diff1.get(Calendar.DAY_OF_YEAR) != firstDate.get(Calendar.DAY_OF_YEAR)){
                diff1.add(Calendar.YEAR, - firstDate.get(Calendar.YEAR));         
                diff1.add(Calendar.DAY_OF_YEAR, - firstDate.get(Calendar.DAY_OF_YEAR)); 
                // Nbre jour ecart
                 dayCount = diff1.get(Calendar.DAY_OF_YEAR);            
              } else{ 
                dayCount =0;
              }
              
              int begin = 50 + (int)(dayCount* stepx);

              int endDayCount = 0;
              // Calcul de la pos de fin
              Calendar diff2 =(Calendar)t.getEarliestEndTime().clone();//.getActualEndTime().clone();
              
              if (diff2.get(Calendar.DAY_OF_YEAR) != firstDate.get(Calendar.DAY_OF_YEAR)){
                diff2.add(Calendar.YEAR, - firstDate.get(Calendar.YEAR));         
                diff2.add(Calendar.DAY_OF_YEAR, - firstDate.get(Calendar.DAY_OF_YEAR)); 
                
              // Nbre jour ecart
               endDayCount = 50 + (int)(diff2.get(Calendar.DAY_OF_YEAR)*stepx+ stepx);            
              }else              
               endDayCount = 50 + (int)(stepx); 
              
               
               System.out.println("tache : " + t.getName()+ "begin : " + begin + " end : " + endDayCount + " y : " + posY);
              
              Rectangle rectClip = new Rectangle (begin , 50 + posY + dec*50,
                      endDayCount-begin , 50);
              
              g2d.clip(rectClip);
              
              g2d.setClip(clip1);
                 
              // Dessin de la tache
              
                            // Dessin de la tache
              if (!t.isCritical())
                g2d.setColor(c);
              else
                g2d.setColor(new Color(255,130,130));
              
              g2d.fillRoundRect( begin ,50 + posY + dec*50, 
                                 endDayCount-begin , 50,18, 18);

              // Contour fonce              
              g2d.setPaint(p1);    
              g2d.drawRoundRect( begin , 50 + posY+ dec*50, 
                      endDayCount-begin , 50- 1, 20, 20);        

              if (!t.isCritical())
                g2d.setColor(c);
              else
                g2d.setColor(new Color(255,190,190));


              g2d.drawRoundRect(1+ begin ,50 + posY+ dec*50+1, 
                      endDayCount-begin , 50 - 3, 18, 18);
                      
                // Haut de la note
              g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f));

              Rectangle rectClipTop = new Rectangle (begin , 50 + posY+ dec*50,
                      endDayCount-begin , 25);
              
               g2d.setClip(clip1);
                 
              g2d.clip(rectClipTop);
              
              if (t.isCritical())
                 gradient = new GradientPaint(begin, 50 + posY+ dec*50+1,Color.RED,
                            endDayCount-begin ,posY+ dec*50+50,Color.WHITE);
              else
                gradient = new GradientPaint(begin, 50 + posY+ dec*50+1,c,
                            endDayCount-begin ,posY+ dec*50+50,Color.WHITE);
              
              g2d.setPaint(gradient);
              g2d.fillRoundRect( begin , 50 + posY+ dec*50+1,
                      endDayCount-begin, 50-1,18, 18);
              
             /* if (testNote.isSelected()){
                g2d.setColor(Color.WHITE);
                g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f));
                g2d.fillRoundRect( testNote.getXPos()* columnWidth +1, 
                                (int)(testNote.getNoteZone().y), columnWidth-2, (int)testNote.getNoteZone().getHeight()-1,18, 18);
                g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.9f));
              }
            */
            g2d.setColor(new Color (60,10,10));  
            g2d.setFont(new java.awt.Font("Comic Sans MS", 1, 12));
            g2d.drawString(t.getName(), begin +5,
                    50 + posY+ dec*50+13);
 
            
            
              // Bas de la note
              g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f));

              Rectangle rectClipBottom = new Rectangle (begin , 50 + posY+ dec*50+25,
                      endDayCount , 25);
              
               g2d.setClip(clip1);
                 
              g2d.clip(rectClipBottom);
              
              if (t.isCritical())
                 gradient = new GradientPaint(begin, 50 + posY+ dec*50+1,Color.RED,
                            endDayCount-begin ,posY+ dec*50+50,Color.WHITE);
              else
                gradient = new GradientPaint(begin, 50 + posY+ dec*50+1,c,
                            endDayCount-begin ,posY+ dec*50+50,Color.WHITE);
              
              g2d.setPaint(gradient);
              g2d.fillRoundRect( begin , 50 + posY+ dec*50+1,
                      endDayCount-begin , 50-1,18, 18);
              
             /* if (testNote.isSelected()){
                g2d.setColor(Color.WHITE);
                g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f));
                g2d.fillRoundRect( testNote.getXPos()* columnWidth +1, 
                                (int)(testNote.getNoteZone().y), columnWidth-2, (int)testNote.getNoteZone().getHeight()-1,18, 18);
                g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.9f));
              }
            */
            g2d.setColor(new Color (60,10,10));  
            
            g2d.setFont(new java.awt.Font("Comic Sans MS", 1, 12));
            g2d.drawString(t.getEarliestBeginTime().getTime().toString().substring(0, 10),
//            g2d.drawString(t.getActualBeginTime().getTime().toString().substring(0, 10),
                    begin +5,50 +posY+ dec*50+38);
           
            Calendar temp3 = Calendar.getInstance();
            temp3.setTime(t.getEarliestEndTime().getTime());
            temp3.add(Calendar.DAY_OF_YEAR, 1);            
            
            g2d.drawString(temp3.getTime().toString().substring(0, 10), 
            //g2d.drawString(t.getActualEndTime().getTime().toString().substring(0, 10), 
                    endDayCount -90 , 50 + posY+ dec*50+38);
            
            
            
            g2d.setClip(clip1);
            
            

            return true;
            }         
            return false;
       }
       
       
      @Override
      protected void paintComponent(Graphics g) {
        int tot = workSpace.getCurrentTask().getTaskList(true,true).size()+2;
        if (tot>7){
            height= (tot-1)*100;
            fixedHeight = true;
            g.getClipBounds().height = height;
            this.setPreferredSize(new Dimension (width, height));
            ganttPanel.setPreferredSize(new Dimension ( width , height));
        }else{
            fixedHeight = false;
        }
          
        // List de Tache courante
        LinkedList<Task> list= workSpace.getCurrentTask().getTaskList(false,false);
        
        // Nombre de div
        int yDiv = list.size();
        
        // Taille utile de l'écran
        width = g.getClipBounds().width;
        if (!fixedHeight)
          height = g.getClipBounds().height;
     
        g.setColor(Color.DARK_GRAY);
           
        // Bordure de la zone
        g.drawRoundRect( 50 , 50, 
                      width-100 , height- 100, 20, 20); 
     
        // Grille
        if (yDiv>1){
          int yDivSize = (height-100)/ (yDiv-1);
          
          for (int i = 1 ;i < yDiv-1; i++){
            int j = 50;
            while (j < width-55){
              if (j % 10 == 0)
                g.drawLine(j, 50 + i*yDivSize, j+5, 50+ i*yDivSize);
              j+=5;
            }
          }
        }
        
        
        // Calcul de l'interval
        Calendar firstDate, lastDate;
        Calendar diff;
        int days= 0;
        int month = 0;
        
        if (yDiv>1){
          firstDate = list.getFirst().getEarliestBeginTime();//.getActualBeginTime();
          lastDate = list.getFirst().getEarliestEndTime();//.getActualEndTime();
          for (Task t : list){
            if (t.getEarliestBeginTime().before(firstDate))
              firstDate = t.getEarliestBeginTime();
            if (t.getEarliestEndTime().after(lastDate))
              lastDate = t.getEarliestEndTime();       
          }
          
          diff =(Calendar)lastDate.clone();
          diff.add(Calendar.YEAR, - firstDate.get(Calendar.YEAR));         
          diff.add(Calendar.DAY_OF_YEAR, - firstDate.get(Calendar.DAY_OF_YEAR)); 
          
          // Nbre jour ecart
          if (firstDate.get(Calendar.DAY_OF_YEAR) == lastDate.get(Calendar.DAY_OF_YEAR) &&
               firstDate.get(Calendar.YEAR) == lastDate.get(Calendar.YEAR))
            days = 1;
          else
              days = diff.get(Calendar.DAY_OF_YEAR) +1;
          
          
          // Affichage debut fin en bas
          g.drawString(firstDate.getTime().toString().substring(0,12), 40, height-20);
          Calendar temp1 = Calendar.getInstance();
          temp1.setTime(lastDate.getTime());
          temp1.add(Calendar.DAY_OF_YEAR, 1);
          g.drawString(temp1.getTime().toString().substring(0,12), g.getClipBounds().width-70, height-20);

          
          /////////////////////////////////
          // Grille vertical des mois
          
          g.setColor(Color.LIGHT_GRAY);
          
          // Taille d'une journee al 'ecran
          float stepx = days !=0?
            (width -100) / days : 
            (width-100) ;
          // num du mois de début
          int monthNum = firstDate.get(Calendar.MONTH);
          // decalage jusqu'au mois suivant
          int firstVert = dayMonthNumb[monthNum] - firstDate.get(Calendar.DAY_OF_MONTH);
          // Position de la premierer verticale
          int xPos = 50 + (int)(firstVert* stepx);


          
          // DEcalage de la date de debut
          Calendar tempDate = (Calendar)firstDate.clone();
          tempDate.add(Calendar.DAY_OF_YEAR, firstVert+1);
          
          // On dessine les traits verticaux
          while (xPos <= height-50){
            int j = 50;
            while (j < height-50){
              if (j % 10 == 0)
                g.drawLine(xPos, j, xPos, j+5);
              j+=5;
            }

            // Affichage date
            g.drawString(tempDate.getTime().toString().substring(0,10), xPos-20, height-20);
           
            // mois suivant
            monthNum = (monthNum+1)%12;
                        
            // Decalage jusqu'au mois suiavnt
            xPos=  xPos + (int)(dayMonthNumb[monthNum]* stepx);
            tempDate.add( Calendar.DAY_OF_YEAR, dayMonthNumb[monthNum]);
            
          }
          
          int i =0;
          // Recuperation du graphics de dessin
          Graphics2D g2d = (Graphics2D)g.create();
          
          int j=0;
          Color  c= tabColor[j];

          int Ypos =0;
          
          Collections.sort(list);
          // On dessine les taches
          for (Task t : list){
            j=0;
            tot++;
            // On ne dessine pas la tache en cours
            if (t.getID() != workSpace.getCurrentTask().getID()){
              paintTasks(t,g2d,firstDate, lastDate, days, Ypos,j, i,c);
              if (t.getTaskList(true,false).size()>1){
                int k = 0;
                Task temp = t.getSuperTask();
                while (temp!=null){
                  k++;
                  temp = temp.getSuperTask();
                }
                if ( k ==0) k =1;
                Ypos+= (t.getTaskList(true,false).size())*50 + k*50;
              }else{
                Ypos+= 100;
              }
              i++;
            }
          }
        }
        
        
        
      }

    }
}

/////////////////////////////////////////////////////////////////////////
